package com.youchuang.helper;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Repository("hibernateHelper")
@SuppressWarnings("all")
public class HibernateHelperImpl<T> implements HibernateHelper<T> {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }


    @Override
    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public T get(String hql, List<Object> param) {
        List<T> l = this.find(hql, param);
        if (l != null && l.size() > 0) {
            return (T) l.get(0);
        }
        return null;
    }

    @Override
    public List<T> find(String hql, int page, int rows, List<Object> param) {
        Query q = this.getCurrentSession().createQuery(hql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
    }


    @Override
    public List<Object[]> findBySQL(String sql) {
        return this.getCurrentSession().createSQLQuery(sql).list();
    }

    @Override
    public List<T> find(String hql, List<Object> param) {
        Query q = this.getCurrentSession().createQuery(hql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return q.list();
    }

    @Override
    public T get(Class<T> c, Serializable id) {
        return (T) this.getCurrentSession().get(c, id);
    }


    public Long count(String hql, List<Object> param) {
        Query q = this.getCurrentSession().createQuery(hql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return (Long) q.uniqueResult();
    }

    @Override
    public Long countBySql(String sql, List<Object> param) {
        Query q = this.getCurrentSession().createSQLQuery(sql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return ((BigDecimal) q.uniqueResult()).longValue();
    }

    @Override
    public String save(T o) {
        return (String) this.getCurrentSession().save(o);
    }

    /**
     * 更新一个对象
     *
     * @param o 对象
     */
    @Override
    public void update(T o) {
        this.getCurrentSession().update(o);
    }

    /**
     * 更新一个对象
     *
     * @param o 对象
     */
    public void merge(T o) {
        this.getCurrentSession().merge(o);
    }

    @Override
    public void delete(T o) {
        this.getCurrentSession().delete(o);
    }

    @Override
    public Integer executeHql(String hql, List<Object> param) {
        Query q = this.getCurrentSession().createQuery(hql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return q.executeUpdate();
    }

    @Override
    public Criteria getCriteria(Class<T> c, Map<String, Object> param) {
        Criteria cri = this.getCurrentSession().createCriteria(c);
        if (param != null) {
            Set keyset = param.keySet();
            for (Object key : keyset) {
                if (key == null || param.get(key) == null) {
                    continue;
                }
                if (param.get(key).getClass() == String.class) {
                    cri.add(Restrictions.like(key.toString(),
                            param.get(key)));
                } else {
                    cri.add(Restrictions.eq(key.toString(), param
                            .get(key)));
                }
            }
        }
        return cri;
    }

    public void saveOrUpdate(T o) {
        this.getCurrentSession().saveOrUpdate(o);
    }

    @Override
    public Integer executeSql(String sql, List<Object> param) {
        Query q = this.getCurrentSession().createSQLQuery(sql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.size());
            }
        }
        return q.executeUpdate();
    }


    @Override
    public List<Object[]> fildBySQL(String sql, List<Object> param) {
        Query q = this.getCurrentSession().createSQLQuery(sql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return q.list();
    }

    @Override
    public List<Object[]> findBySql(String sql, int page, int rows, List<Object> param) {
        Query q = this.getCurrentSession().createSQLQuery(sql);
        if (param != null && param.size() > 0) {
            for (int i = 0; i < param.size(); i++) {
                q.setParameter(i, param.get(i));
            }
        }
        return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
    }

}